global class MC_IncomingEmail implements Messaging.InboundEmailHandler
{
    global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope)
    {   
        Set<String> toAddresses=new Set<String>();
        if(email.toAddresses!=null)
            toAddresses.AddAll(email.toAddresses);
        if(email.ccAddresses!=null)
            toAddresses.AddAll(email.ccAddresses);
        
        System.Debug('Received mail from '+email.fromAddress+' to:');
        System.Debug(toAddresses);
        
        //Try to find groups with a leader having the from address we received
        List<Missional_Community_Member__c> leaderMembership=
            [
                select
                    Id
                    ,Missional_Community__c
                from
                    Missional_Community_Member__c
                where
                    Contact__r.Email=:email.fromAddress
                    and Role__c='Leader'
            ];
        List<Id> leaderGroupIds=new List<Id>();
        for(Missional_Community_Member__c member : leaderMembership)
            leaderGroupIds.Add(member.Missional_Community__c);
        List<Missional_Community__c> leaderGroups=
            [
                select
                    Id
                    ,(select Contact__r.Email from Missional_Community_Members__r where Role__c<>'Leader')
                from
                    Missional_Community__c
                where
                    Id in : leaderGroupIds
            ];
            
        if(leaderMembership==null || leaderMembership.size()==0)
            return null;    //This email wasn't from a leader. Silently drop it.
            
        List<Missional_Community_Member__c> leadersMembers=new List<Missional_Community_Member__c>();
        for(Missional_Community__c theGroup : leaderGroups)
            for(Missional_Community_Member__c member : theGroup.Missional_Community_Members__r)
                leadersMembers.Add(member);
        
        //See if the special "SalesforceEmailAll" address is in the TO
        if(toAddresses.contains(SalesforceEmailAll))
        {
            //All the members of this leader's group (groups) are considered contacted
            for(Missional_Community_Member__c member : leadersMembers)
                member.Has_Been_Contacted__c=true;
            System.Debug('Bulk updating '+leadersMembers.size()+' members from leader '+email.fromAddress);
            update leadersMembers;
            return null;
        }
        
        //Search for members in the TO list
        List<Missional_Community_Member__c> membersToSave=new List<Missional_Community_Member__c>();
        for(Missional_Community_Member__c member : leadersMembers)
        {
            if(toAddresses.contains(member.Contact__r.Email))
            {
                System.Debug('Member '+member.Contact__r.Email+' has been contacted.');
                member.Has_Been_Contacted__c=true;
                membersToSave.Add(member);
            }
        }
        update membersToSave;
        
        return null;
    }
    
    private static String SalesforceEmailAll { get {return 'contactverificationall@austinstone.org';} }    //XYZZY make this a configuration option
    
    public static testmethod void Test1()
    {
    	//Put together some test data
    	Missional_Community__c aGroup=new Missional_Community__c();
    	Contact aLeader=new Contact();
    	aLeader.AccountId=[select id from Account where Name='Missional Community Members' limit 1].Id;
    	aLeader.FirstName='LeaderFirst';
    	aLeader.LastName='LeaderLast';
    	aLeader.Email='leader@email.bad';
    	insert aGroup;
    	insert aLeader;
    	Missional_Community_Member__c aGroupMember=new Missional_Community_Member__c();
    	aGroupMember.Contact__c=aLeader.Id;
    	aGroupMember.Missional_Community__c=aGroup.Id;
    	aGroupMember.Role__c='Leader';
    	insert aGroupMember;
    	
    	Contact aMember1=new Contact();
    	aMember1.AccountId=[select id from Account where Name='Missional Community Members' limit 1].Id;
    	aMember1.FirstName='Member1First';
    	aMember1.LastName='Member1Last';
    	aMember1.Email='member1@email.bad';
    	insert aMember1;
    	Missional_Community_Member__c aGroupMember2=new Missional_Community_Member__c();
    	aGroupMember2.Contact__c=aMember1.Id;
    	aGroupMember2.Missional_Community__c=aGroup.Id;
    	aGroupMember2.Role__c='Member';
    	insert aGroupMember2;
    	
    	Contact aMember2=new Contact();
    	aMember2.AccountId=[select id from Account where Name='Missional Community Members' limit 1].Id;
    	aMember2.FirstName='Member2First';
    	aMember2.LastName='Member2Last';
    	aMember2.Email='member2@email.bad';
    	insert aMember2;
    	Missional_Community_Member__c aGroupMember3=new Missional_Community_Member__c();
    	aGroupMember3.Contact__c=aMember2.Id;
    	aGroupMember3.Missional_Community__c=aGroup.Id;
    	aGroupMember3.Role__c='Member';
    	insert aGroupMember3;
    	
    	aGroupMember2=[select Has_Been_Contacted__c from Missional_Community_Member__c where Id=:aGroupMember2.id];
    	System.assertEquals(false, aGroupMember2.Has_Been_Contacted__c);
    	
    	 
    	Messaging.InboundEmail incomingEmail=new Messaging.InboundEmail();
    	incomingEmail.fromAddress='noonehere@email.bad';
    	incomingEmail.toAddresses=new String[] {'member1@email.bad'};
 
 		Messaging.InboundEmailResult result;
 		Messaging.InboundEnvelope envelope=new Messaging.InboundEnvelope();
 		MC_IncomingEmail handler=new MC_IncomingEmail();
 		result=handler.handleInboundEmail(incomingEmail, envelope);
 		System.assertEquals(null, result);
 		
    	aGroupMember2=[select Has_Been_Contacted__c from Missional_Community_Member__c where Id=:aGroupMember2.id];
    	System.assertEquals(false, aGroupMember2.Has_Been_Contacted__c);

		incomingEmail.fromAddress='leader@email.bad';
		incomingEmail.toAddresses=new String[] {'member1@email.bad'};
		
		result=handler.handleInboundEmail(incomingEmail, envelope);
		System.assertEquals(null, result);
		
		aGroupMember2=[select Has_Been_Contacted__c from Missional_Community_Member__c where Id=:aGroupMember2.id];
    	System.assertEquals(true, aGroupMember2.Has_Been_Contacted__c);
    	
    	aGroupMember3=[select Has_Been_Contacted__c from Missional_Community_Member__c where Id=:aGroupMember3.id];
    	System.assertEquals(false, aGroupMember3.Has_Been_Contacted__c);
		
		incomingEmail.fromAddress='leader@email.bad';
		incomingEmail.toAddresses=new String[]{SalesforceEmailAll};
		
		result=handler.handleInboundEmail(incomingEmail, envelope);
		System.assertEquals(null, result);
		
		aGroupMember3=[select Has_Been_Contacted__c from Missional_Community_Member__c where Id=:aGroupMember3.id];
    	System.assertEquals(true, aGroupMember3.Has_Been_Contacted__c);
    }
}